<?php

defined('BASEPATH') or die('forbidden');

/**
 * 上传类
 * @author  Karson
 * @name    upload.php
 * @since   2011-03-19 15:39:18
 */
class Upload {

    var $files = array();
    var $max_size;
    var $suffix;
    var $folder;
    var $overwrite;

    //构造函数
    function __construct() {
        $this->max_size = UPLOAD_MAX_SIZE;
        $this->suffix = UPLOAD_SUFFIX;
        $this->folder = UPLOAD_FOLDER;
        $this->overwrite = UPLOAD_OVERWRITE;
    }

    /**
     * 上传文件
     * @param string $name 表单中的文件名称
     * @param string $new_name 新文件名称，默认为null，即不改变文件名
     * @param bool $overwrite 是否覆盖已经存在的文件，默认为false，即不覆盖
     * @param string $suffix 允许上传的文件后缀，默认为null，根据常量设置
     * @param int $max_size 最大允许上传的大小，默认为null，根据常量设置
     * @param string $folder 上传到的文件夹，默认为null，根据常量设置
     * @return mixed 成功返回上传文件的URL，失败返回false
     */
    public function do_upload($name, $new_name = null, $overwrite = false, $suffix = null, $max_size = null, $folder = null) {
        if (isset($_FILES[$name])) {
            $this->files[$name] = $_FILES[$name];
        } else {
            $this->set_error($name, 9, '表单中不存在上传的文件名');
            return false;
        }

        //判断是否选择了文件
        if ($this->files[$name]['name'] == '') {
            $this->set_error($name, 10, '未选择上传的文件');
            return false;
        }

        //获取上传文件的信息
        preg_match("/\.([^\.]+)$/i", $this->files[$name]['name'], $extension);
        $this->files[$name]['extension'] = '.' . strtolower($extension[1]);

        //构造上传文件名
        if ($new_name && !is_null($new_name)) {
            $this->files[$name]['new_name'] = (substr($new_name, -strlen($this->files[$name]['extension']), strlen($this->files[$name]['extension'])) != $this->files[$name]['extension']) ? $new_name . $this->files[$name]['extension'] : $new_name;
        } else {
            $this->files[$name]['new_name'] = $this->files[$name]['name'];
        }

        $this->files[$name]['suffix'] = $suffix && is_string($suffix) ? $suffix : $this->suffix;
        $this->files[$name]['max_size'] = $max_size && is_numeric($max_size) ? intval($max_size) : intval($this->max_size);
        $this->files[$name]['folder'] = $folder && is_string($folder) ? $folder : $this->folder;
        $this->files[$name]['overwrite'] = $overwrite ? true : false;
        //判断文件大小是否超过限制
        if ($this->files[$name]['size'] > $this->files[$name]['max_size']) {
            $this->set_error($name, 11, '上传的文件超过指定大小');
            return false;
        }
        //判断文件类型是否允许
        if ($this->files[$name]['suffix'] != '*' && !in_array($this->files[$name]['extension'], explode(',', $this->files[$name]['suffix']))) {
            $this->set_error($name, 12, '不允许上传的文件类型');
            return false;
        }
        //构造返回的URL和上传的文件路径
        $this->files[$name]['folder'] .= ( substr($this->files[$name]['folder'], -1) != '/' || substr($this->files[$name]['folder'], -1) != '\\') ? '/' : '';
        $this->files[$name]['url'] = '/' . $this->files[$name]['folder'] . $this->files[$name]['new_name'];
        $this->files[$name]['base_path'] = $this->files[$name]['folder'];

        //创建目录
        mk_dir($this->files[$name]['base_path']);
        if (!is_readable($this->files[$name]['base_path'])) {
            $this->set_error($name, 13, '上传目录不可写');
            return false;
        }

        $this->files[$name]['path'] = $this->files[$name]['base_path'] . $this->files[$name]['new_name'];
        //判断是否存在相同文件名文件
        if (file_exists($this->files[$name]['path'])) {
            //如果为覆盖模式，则删除已经存在的文件，反之上传失败
            if ($this->files[$name]['overwrite']) {
                @unlink($this->files[$name]['path']);
            } else {
                $this->set_error($name, 14, '文件已经存在');
                return false;
            }
        }
        //开始上传
        if (!move_uploaded_file($this->files[$name]['tmp_name'], iconv('utf-8', 'gbk', $this->files[$name]['path']))) {
            $this->set_error($name, 15, '上传文件失败');
            return false;
        } else {
            @unlink($this->files[$name]['tmp_name']);
            $this->set_error($name, 0, '上传文件成功');
            return $this->files[$name]['url'];
        }
    }

    /**
     * 获取上传数据
     * @return array 返回上传的数据信息
     */
    function data() {
        $temp = array();
        foreach ($this->files as $key => $value) {
            unset($value['base_path'], $value['path'], $value['tmp_name']);
            $temp[$key] = $value;
        }
        return $temp;
    }

    /**
     * 设置错误信息
     * @param name $name 上传文件名称
     * @param int $id 错误代号
     * @param string $msg 错误信息
     */
    function set_error($name, $id, $msg) {
        $this->files[$name]['error'] = $id;
        $this->files[$name]['error_msg'] = $msg;
    }

}
